package com.jzo2o.orders.manager.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.api.trade.NativePayApi;
import com.jzo2o.api.trade.TradingApi;
import com.jzo2o.api.trade.dto.request.NativePayReqDTO;
import com.jzo2o.api.trade.dto.response.NativePayResDTO;
import com.jzo2o.api.trade.dto.response.TradingResDTO;
import com.jzo2o.api.trade.enums.PayChannelEnum;
import com.jzo2o.api.trade.enums.TradingStateEnum;
import com.jzo2o.common.expcetions.CommonException;
import com.jzo2o.common.model.msg.TradeStatusMsg;
import com.jzo2o.common.utils.ObjectUtils;
import com.jzo2o.orders.base.enums.OrderPayStatusEnum;
import com.jzo2o.orders.base.enums.OrderStatusEnum;
import com.jzo2o.orders.base.mapper.OrdersMapper;
import com.jzo2o.orders.base.model.domain.Orders;
import com.jzo2o.orders.manager.model.dto.request.OrdersPayReqDTO;
import com.jzo2o.orders.manager.model.dto.response.OrdersPayResDTO;
import com.jzo2o.orders.manager.porperties.TradeProperties;
import com.jzo2o.orders.manager.service.IOrdersCreateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * <p>
 * 下单服务类
 * </p>
 *
 * @author itcast
 * @since 2023-07-10
 */
@Slf4j
@Service
public class OrdersCreateServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersCreateService {

    @Resource
    private TradeProperties tradeProperties;
    @Resource
    private NativePayApi nativePayApi;
    @Resource
    private TradingApi tradingApi;

    /**
     * 订单支付[获取支付地址（二维码）]
     * @param id              订单id
     * @param ordersPayReqDTO 订单支付请求体
     * @return 订单支付响应体
     */
    @Override
    public OrdersPayResDTO pay(Long id, OrdersPayReqDTO ordersPayReqDTO) {
        //1、检查订单是否存在
        Orders orders = getById(id);
        if(ObjectUtil.isEmpty(orders)){
            throw new CommonException("订单不存在！");
        }

        //2、订单如果已经支付，直接返回
        if(orders.getPayStatus()== OrderPayStatusEnum.PAY_SUCCESS.getStatus()){
            OrdersPayResDTO ordersPayResDTO = new OrdersPayResDTO();
            BeanUtil.copyProperties(ordersPayReqDTO,ordersPayResDTO);
            ordersPayResDTO.setProductOrderNo(orders.getId());
            return ordersPayResDTO;
        }else{
            //3、未支付，生成二维码
            NativePayResDTO nativePayResDTO = generateQrCode(orders, ordersPayReqDTO.getTradingChannel());
            OrdersPayResDTO ordersPayResDTO = BeanUtil.toBean(nativePayResDTO, OrdersPayResDTO.class);
            return ordersPayResDTO;
        }
    }

    /**
     * 创建支付交易记录，获取支付二维码
     * @param orders
     * @param tradingChannel
     * @return
     */
    public NativePayResDTO generateQrCode(Orders orders, PayChannelEnum tradingChannel){
        //判断支付渠道
        Long enterpriseId = ObjectUtil.equal(PayChannelEnum.ALI_PAY, tradingChannel) ?
                tradeProperties.getAliEnterpriseId() : tradeProperties.getWechatEnterpriseId();

        //构建支付请求参数
        NativePayReqDTO nativePayReqDTO = new NativePayReqDTO();
        //商户号
        nativePayReqDTO.setEnterpriseId(enterpriseId);
        //业务系统标识
        nativePayReqDTO.setProductAppId("jzo2o.orders");
        //家政订单号
        nativePayReqDTO.setProductOrderNo(orders.getId());
        //支付渠道
        nativePayReqDTO.setTradingChannel(tradingChannel);
        //支付金额
        nativePayReqDTO.setTradingAmount(orders.getRealPayAmount());
        //备注信息
        nativePayReqDTO.setMemo(orders.getServeItemName());
        //判断是否切换支付渠道
        if (ObjectUtil.isNotEmpty(orders.getTradingChannel())
                && ObjectUtil.notEqual(orders.getTradingChannel(), tradingChannel.toString())) {
            nativePayReqDTO.setChangeChannel(true);
        }
        //生成支付二维码
        NativePayResDTO downLineTrading = nativePayApi.createDownLineTrading(nativePayReqDTO);
        if(ObjectUtils.isNotNull(downLineTrading)){
            log.info("订单:{}请求支付,生成二维码:{}",orders.getId(),downLineTrading.toString());
            //将二维码更新到交易订单中
            boolean update = lambdaUpdate()
                    .eq(Orders::getId, downLineTrading.getProductOrderNo())
                    .set(Orders::getTradingOrderNo, downLineTrading.getTradingOrderNo())
                    .set(Orders::getTradingChannel, downLineTrading.getTradingChannel())
                    .update();
            if(!update){
                throw new CommonException("订单:"+orders.getId()+"请求支付更新交易单号失败");
            }
        }
        return downLineTrading;
    }

    @Override
    public OrdersPayResDTO getPayResultFromTradServer(Long id) {
        // 1、查询订单，如果不存在，直接抛出异常
        Orders orders = getById(id);
        if(ObjectUtil.isEmpty(orders)){
            throw new CommonException("订单不存在");
        }
        // 2、订单处于未支付状态，查询微信服务，获取支付状态，并同步更新到订单表
        if(ObjectUtil.equal(orders.getPayStatus(), OrderPayStatusEnum.NO_PAY.getStatus())
        && ObjectUtil.isNotEmpty(orders.getTradingOrderNo())){
            // 查询微信服务[判断订单是否已支付，如果未支付，查询微信服务器，并将状态更新到交易订单表，并且返回]
            // 2、1调用支付服务
            TradingResDTO tradResult = tradingApi.findTradResultByTradingOrderNo(orders.getTradingOrderNo());
            if(ObjectUtil.isNotEmpty(tradResult)){
                // 2、2获取支付服务返回结果
                // 支付状态、微信服务器返回的订单号、订单状态修改
                // 2、3同步更新到数据库
                boolean update = lambdaUpdate()
                        .set(ObjectUtil.equal(tradResult.getTradingState(), TradingStateEnum.YJS),Orders::getPayStatus, OrderStatusEnum.DISPATCHING.getStatus())
                        .set(ObjectUtil.equal(tradResult.getTradingState(), TradingStateEnum.FKSB),Orders::getPayStatus, OrderStatusEnum.CLOSED.getStatus())
                        .set(ObjectUtil.equal(tradResult.getTradingState(), TradingStateEnum.QXDD),Orders::getPayStatus, OrderStatusEnum.CANCELED.getStatus())
                        // 已取消【5】 支付成功【4】 支付失败【3】
                        .set(ObjectUtil.isNotEmpty(tradResult.getTransactionId()),Orders::getPayStatus, OrderPayStatusEnum.PAY_SUCCESS.getStatus())
                        .set(ObjectUtil.isNotEmpty(tradResult.getTransactionId()),Orders::getTransactionId, tradResult.getTransactionId())
                        .eq(Orders::getId, tradResult.getProductOrderNo())
                        .update();
                if(!update){
                    throw new CommonException("当前服务器繁忙，请稍后再试！");
                }

                orders = getById(id);
                // 2、4返回数据封装
                OrdersPayResDTO bean = BeanUtil.toBean(tradResult, OrdersPayResDTO.class);
                bean.setPayStatus(orders.getPayStatus());
                return bean;
            }
        }
        // 3、当前订单不是未支付状态，直接返回
        OrdersPayResDTO ordersPayResDTO = new OrdersPayResDTO();
        ordersPayResDTO.setProductOrderNo(orders.getId());
        ordersPayResDTO.setTradingOrderNo(orders.getTradingOrderNo());
        ordersPayResDTO.setTradingChannel(orders.getTradingChannel());
        ordersPayResDTO.setPayStatus(orders.getPayStatus());
        return ordersPayResDTO;
    }

    /**
     * 更新支付最终状态
     * @param tradeStatusMsg 交易状态消息
     */
    @Override
    public void paySuccess(TradeStatusMsg tradeStatusMsg) {
        //1、判断订单是否存在
        Orders order = getById(tradeStatusMsg.getProductOrderNo());
        if (order == null){
            throw new CommonException("订单不存在！");
        }
        //2、订单如果不是待支付状态，不做任何处理
        if(ObjectUtil.equal(order.getPayStatus(), OrderPayStatusEnum.NO_PAY.getStatus()) && ObjectUtil.equal(order.getOrdersStatus(), OrderPayStatusEnum.NO_PAY.getStatus())){
            log.info("当前订单已完成状态修改！");
            return;
        }
        //3、是否缺少第三方交易单号
        if(ObjectUtil.isEmpty(tradeStatusMsg.getTransactionId())){
            throw new CommonException("订单状态已修改，但未检测到第三方交易单号！");
        }
        //4、执行修改
        Integer statusCode = tradeStatusMsg.getStatusCode();
        boolean update = lambdaUpdate()
                .set(ObjectUtil.equal(statusCode, TradingStateEnum.YJS.getCode()), Orders::getOrdersStatus, OrderStatusEnum.DISPATCHING.getStatus())
                .set(ObjectUtil.equal(statusCode, TradingStateEnum.FKSB.getCode()), Orders::getOrdersStatus, OrderStatusEnum.CLOSED.getStatus())
                .set(ObjectUtil.equal(statusCode, TradingStateEnum.QXDD.getCode()), Orders::getOrdersStatus, OrderStatusEnum.CANCELED.getStatus())
                .set(ObjectUtil.equal(statusCode, TradingStateEnum.YJS.getCode()), Orders::getOrdersStatus, OrderPayStatusEnum.PAY_SUCCESS.getStatus())
                .set(ObjectUtil.isNotEmpty(tradeStatusMsg.getTransactionId()), Orders::getTransactionId, tradeStatusMsg.getTransactionId())
                .eq(Orders::getId, tradeStatusMsg.getProductOrderNo())
                .update();
        if(!update){
            log.info("更新订单:{}支付失败", order.getId());
            throw new CommonException("更新订单"+order.getId()+"支付失败");
        }
    }
}
